文章目录
  1. 非结构化数仓建模和Schema-Less OLAP构建 - 优化分层数仓(一)
  2. 一、概述
  3. 二、预聚合层的尴尬
    1. 2.1 示例
    2. 2.2 优缺点
  4. 三、优化预聚合层
    1. 3.1 优化设备数
    2. 3.2 优化指标
    3. 3.3 小节
  5. 四、兼容维表
  6. 五、总结

同步更新:https://icemimosa.notion.site/Schema-Less-OLAP-3d8b1bbcd4e6434eadbe95b86eceb9a9

非结构化数仓建模和Schema-Less OLAP构建 - 优化分层数仓(一)

一、概述

上篇文档 非结构化数仓建模和Schema-Less OLAP构建(零) 我们宏观讲述了如何基于bitmap来作为非结构化建模的底层数据结构,以及在存储、计算和应用方面所带来的好处。那么本节开始将从微观的角度,讲述非结构化数仓具体的建设思路,bitmap数据结构的使用,以及如何搭建Schema-Less OLAP。

由于非结构数仓建模是一套完整的建模体系,区别于当前分层建模的思路。所以本节将结合其中一部分进行讲述,且如何让它在分层数仓建模中起到一个补充优化的作用。

PS:完整的建模思路将在该系列文章最后进行讲述(挖坑)。

二、预聚合层的尴尬

2.1 示例

在分层数仓中,为了便于下游分析,我们一般不会将特别明细的数据暴露给下游使用,通常我们会抽出大宽表「预聚合层」。比如如下用户行为数据(table0):

日期 设备ID 城市 操作系统 其他维度… 访问次数 访问时长 分享次数 其他指标…
2022-01-01 1 北京 Windows 1 100 3
2022-01-01 1 上海 Windows 1 200 1
2022-01-01 2 北京 Mac 1 100 1

当然上面的数据已经是「设备」(也可以是其他实体)的粒度了,通常情况下,数据量还是特别大,需要上卷一些维度再进一步做预聚合,比如(table1):

日期 城市 操作系统 其他维度… 设备数 访问次数 访问时长 分享次数 其他指标…
2022-01-01 北京 Windows 1 1 100 3
2022-01-01 上海 Windows 1 1 200 1
2022-01-01 北京 Mac 1 1 100 1

或者这样(table2):

日期 城市 其他维度… 设备数 访问次数 访问时长 分享次数 其他指标…
2022-01-01 北京 2 2 200 4
2022-01-01 上海 1 1 200 1

2.2 优缺点

这样利用空间换时间的方式,可以让下游按需使用最佳的表来优化计算路径,从而减少计算时间、计算资源,保证数据产出的及时性。

但是这种方式的确定也很明显:

  • 需要冗余建设很多类似cube的表,如果后续需要添加指标维度,那么这些表都需要进行修改,且容易出现逻辑口径不一致的问题,难以维护。
  • 没有解决「设备去重数」这类不可累加指标的问题,比如table1table2中的「设备数」无法支持维度上卷。最终可能大多数还是使用table0, 1和2使用比较少。
  • 预聚合的table1table2抹去的设备与指标粒度关系,比如我想看「访问次数>1」的「设备数」这类画像类值的分布,那么将无法满足,还是需要回到table0
  • 如果下游需要对接数据服务,olap查询或者出看板等(比如导入clickhouse),还是比较依赖table1或者table2这类预聚合的表,因为数据量小,查询速度快。但是因为「设备数」无法上卷的问题,比如我想看APP版本维度对应的设备数,table1table2无法满足。此时还是需要导入table0进行查询,但是table0的数据量比较大,这样就陷入比较两难的局面。

由于表中的指标都是结构化的数据,已经丢失了聚合前的信息,所以我们需要利用非结构化的思路来进行优化,以达到通用和复用的目的:

图片路径:[https://github.com/bitlap/drawio/blob/main/2022-01-01.drawio](https://github.com/bitlap/drawio/blob/main/2022-01-01.drawio)

图片路径:https://github.com/bitlap/drawio/blob/main/2022-01-01.drawio

三、优化预聚合层

我们需要借助bitmap数据结构来建设优化后的非结构化表,具体思路如下。

3.1 优化设备数

对于「设备数」这类不可累加型的指标来说,为了让它支持可累加,可以将指标变成bitmap,将table2改造如下,设备数存成bitmap(可对应hive的binary类型):

日期 城市 其他维度… 设备数(bitmap) 访问次数 访问时长 分享次数 其他指标…
2022-01-01 北京 [1,2] 2 200 4
2022-01-01 上海 [1] 1 200 1

这样在执行 select bm_count(bm_agg(设备数)) num from table2 where dt = '2022-01-01' 的时候,就可以很好的支持上卷。

3.2 优化指标

解决了「设备数」的存储,下面需要解决「指标量」的存储。其实一般情况保留成数值类型也没有多大的问题,因为它们都是可累加型的指标,但是有些时候我们做设备画像标签的时候,需要用到(设备→指标)的映射关系。

比如获取「总分享次数=1」的设备数,那么上述的表将无法实现。

为了解决这一问题,需要用到「存储指标量的bitmap」,可以简单参开上篇文章的「指标存储优化」章节,详细的使用后续将开一个新的文章讲解。这里为了显示方便,使用简单的json表达,示例如下:

日期 城市 其他维度… 设备数(bitmap) 访问次数(bitmap) 访问时长(bitmap) 分享次数(bitmap) 其他指标…
2022-01-01 北京 [1,2] {1→[1,2]} {100→[1,2]} {1→[2], 3→[1]}
2022-01-01 上海 [1] {1→[2]} {200→[2]} {1→[1]}

OK,这样获取「总分享次数=1」的设备数可以这样表达:select bm_count(cbm_compute(cbm_agg(分享次数), '=', 1)) num from table2 where dt = '2022-01-01'

  • cbm_agg 将所有的「分享次数」合并,类似sum,比如如上的「分享次数」数据得到结果:{1->[1,2], 3->[1]},设备1做了4次,设备2做了1次
  • cbm_compute 计算「总分享次数=1」,比如得到结果:{1->[2]}
  • bm_count 计算设备数, 根据结果可得只有「设备2」符合,udf计算返回设备数为1

3.3 小节

对于行为类的数据建设,我们需要选取「非结构化实体」作为「bitmap化的对象」,一般会选取「设备」或者「登录用户」。对于如何将String类型的设备标识转化为bitmap所支持的整数类型,这个我们后面会进行讨论,这里假设所有的分析实体已经整数化。

预聚合层的优化本质上是使用「bitmap技术」对「分析实体」进行预聚合,且不丢失原有的含义表达,使得该指标具备上卷和下钻的能力,同时一个指标可以同时表达「累计指标量」和「去重数指标量」。

四、兼容维表

在数仓的维度建模中,事实表和维表在星型模型中是必不可少的组成部分,上节我们对事实的聚合表做了优化,但是维表也需要做一些处理才能兼容去使用。

假设我们做了一个优化后的事实聚合表(dws_table):

日期 维度… 设备数(bitmap) 访问次数(bitmap) 访问时长(bitmap) 分享次数(bitmap) 其他指标…
2022-01-01 [1,2] {1→[1,2]} {100→[1,2]} {1→[2], 3→[1]}
2022-01-01 [1] {1→[2]} {200→[2]} {1→[1]}

假设我们之前我们有一张设备相关的维表,很显然由于事实表设备列的处理,无法与下面的表进行关联:

日期 设备 年龄 性别 其他维度…
2022-01-01 1 20
2022-01-01 2 22

所以对于维表的设备,也要进行「bitmap化」的处理,与事实表的处理方式类似(dim_table):

日期 年龄 性别 其他维度… 维表设备(bitmap)
2022-01-01 20 [1]
2022-01-01 22 [2]

这样维表也能够进行很好的压缩,示例只是做了简单举例,实际情况下也是可以将维表的行数进行有效的削减的。

对于事实表和维表的关联,确实比以往要复杂一些,不像之前只需要使用device_id进行join即可。

现在优化后的dws_table和dim_table做关联的时候,需要做很多的准备工作:

  • 使用bitmap相关技术封装UDF,交集,并集,差集等。
  • dws_table和dim_table使用cross join全关联,然后使用「交集UDF」来判断彼此是否存在交集,比如bitmap_and(访问次数, 维表设备),有交集说明该设备在对应的维表属性中。
  • 关联之后会形成一个新的「非结构化表」,然后在此基础之上在进行后续处理。

五、总结

本节是为了让「非结构化建模」的思想能够使用在当前比较主流的数仓建设中,作为一个有效的补充,避免因数据量大而带来的冗余和重复性建设,其实对于优化后的「事实表」是可以直接对接主流的OLAP引擎的,因为他在数据量上已经足够的小,且能够支持「去重性的指标」,前提是需要OLAP引擎做到对「bitmap」技术的支持。

文章目录
  1. 非结构化数仓建模和Schema-Less OLAP构建 - 优化分层数仓(一)
  2. 一、概述
  3. 二、预聚合层的尴尬
    1. 2.1 示例
    2. 2.2 优缺点
  4. 三、优化预聚合层
    1. 3.1 优化设备数
    2. 3.2 优化指标
    3. 3.3 小节
  5. 四、兼容维表
  6. 五、总结